package com.ruoyi.yipaiju.service.impl;

import com.ruoyi.common.enums.dict.DiligenceReportOrderStatus;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.Builder;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.yipaiju.WeChatPayConfig;
import com.ruoyi.yipaiju.domain.DiligenceReportOrder;
import com.ruoyi.yipaiju.service.IDiligenceReportOrderService;
import com.ruoyi.yipaiju.service.IWechatPayService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class WechatPayServiceImpl implements IWechatPayService {

    private final JsapiService jsapiService;
    private final NotificationParser parser;
    private final WeChatPayConfig wechatPayConfig;
    @Resource
    private ISysConfigService sysConfigService;
    @Resource
    private IDiligenceReportOrderService diligenceReportOrderService;
    public WechatPayServiceImpl(@Autowired WeChatPayConfig wechatPayConfig) {
        this.wechatPayConfig = wechatPayConfig;
        // 参数说明：
        // merchantId - 商户号
        // merchantSerialNumber - 商户证书序列号
        // privateKey - 商户私钥
        // apiV3Key - APIv3密钥
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(wechatPayConfig.getMchId())
                .merchantSerialNumber(wechatPayConfig.getMerchantSerialNumber())
                .privateKey(wechatPayConfig.getPrivateKey())
                .apiV3Key(wechatPayConfig.getApiV3Key())
                .build();

        this.jsapiService = new JsapiService.Builder().config(config).build();

        NotificationConfig notificationConfig = new RSAAutoCertificateConfig.Builder()
                .merchantId(wechatPayConfig.getMchId())
                .merchantSerialNumber(wechatPayConfig.getMerchantSerialNumber())
                .privateKey(wechatPayConfig.getPrivateKey())
                .apiV3Key(wechatPayConfig.getApiV3Key())
                .build();
        this.parser = new NotificationParser(notificationConfig);
    }

    @Override
    public PrepayResponse createJsapiOrder(int productId, String openid, String outTradeNo, long foreclosedId) {
        String body = "";
        String totalFee = "1";
        if (productId == 1){
            body = "人工尽调报告";
            totalFee = sysConfigService.selectConfigByKey("biz.artificial.diligence.report.price");
        }else if (productId == 2){
            body = "AI尽调报告";
            totalFee = sysConfigService.selectConfigByKey("biz.chart.diligence.report.price");
        }

        // 创建金额对象
        Amount amount = new Amount();
        amount.setTotal(Integer.parseInt(totalFee)); // 总金额，单位分
        amount.setCurrency("CNY");

        // 创建支付者对象
        Payer payer = new Payer();
        payer.setOpenid(openid); // 用户的openid

        // 创建预支付请求
        PrepayRequest request = new PrepayRequest();
        request.setAppid(wechatPayConfig.getAppId()); // 公众号或小程序的appid
        request.setMchid(wechatPayConfig.getMchId()); // 商户号
        request.setDescription(body); // 商品描述
        request.setOutTradeNo(outTradeNo); // 商户订单号
//        request.setTimeExpire("2023-12-31T15:59:59+08:00"); // 可选，订单过期时间
//        request.setAttach("自定义数据"); // 可选，附加数据
        request.setNotifyUrl(wechatPayConfig.getNotifyUrl()); // 支付结果通知地址
        request.setAmount(amount);
        request.setPayer(payer);

        // 调用SDK发起预支付
        PrepayResponse response = jsapiService.prepay(request);

        // 生成订单
        DiligenceReportOrder diligenceReportOrder = new DiligenceReportOrder();
        diligenceReportOrder.setProductId(productId);
        diligenceReportOrder.setOpenid(openid);
        diligenceReportOrder.setPayBody(body);
        diligenceReportOrder.setTotalFee(new BigDecimal(totalFee));
        diligenceReportOrder.setOutTradeNo(outTradeNo);
        diligenceReportOrder.setSpbillCreateIp(IpUtils.getHostIp());
        diligenceReportOrder.setStatus(DiligenceReportOrderStatus.PAYING.getValue());
        diligenceReportOrder.setForeclosedId(foreclosedId);
        diligenceReportOrder.setXcxUserId(SecurityUtils.getLoginUser().getXcxUser().getId());
        diligenceReportOrderService.insertDiligenceReportOrder(diligenceReportOrder);

        return response;
    }

    @Override
    public Transaction handleCallback(HttpServletRequest request) {
        // 构建请求参数
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(request.getHeader("Wechatpay-Serial"))
                .nonce(request.getHeader("Wechatpay-Nonce"))
                .timestamp(request.getHeader("Wechatpay-Timestamp"))
                .signature(request.getHeader("Wechatpay-Signature"))
                .body(getRequestBody(request))
                .build();

        // 解析并验签
        return parser.parse(requestParam, Transaction.class);
    }

    private String getRequestBody(HttpServletRequest request) {
        // 从请求中读取body内容
        try {
            return request.getReader().lines().collect(Collectors.joining());
        } catch (IOException e) {
            throw new RuntimeException("Failed to read request body", e);
        }
    }


    @Override
    public Transaction queryOrder(String outTradeNo) {
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setMchid(wechatPayConfig.getMchId());
        request.setOutTradeNo(outTradeNo);

        return jsapiService.queryOrderByOutTradeNo(request);
    }

    @Override
    public List<DiligenceReportOrder> queryOrderList() {
        List<DiligenceReportOrder> list = diligenceReportOrderService.selectDiligenceReportOrderList(Builder.of(DiligenceReportOrder::new).
                with(DiligenceReportOrder::setXcxUserId, SecurityUtils.getLoginUser().getUserId()).build());
        return list;
    }
}
